<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>兵哥版飞机大战</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        #box{
            width: 600px;
            height: 100vh;
            background-color: black;
            margin: 0 auto;
            position: relative;
            overflow: hidden;
        }
        /* 消息样式 */
        #msg{
            width: 100%;
            height: 200px;
            background: rgba(255, 255, 255, 0.4);
            position: absolute;
            top: 150px;
            color: white;
            font-size: 50px;
            line-height: 200px;
            text-align: center;
        }
        /* 飞机样式 */
        #plane{
            width: 60px;
            height: 60px;
            background: url(./img/plane.png) no-repeat center/60px 60px;
            position: absolute;
        }
        /* 敌机样式 */
        .enemy{
            width: 40px;
            height: 40px;
            background: url(./img/plane.png) no-repeat center/40px 40px;
            position: absolute;
            transform: rotate(180deg);
        }
        /* 子弹样式 */
        .bullet{
            width: 8px;
            height: 20px;
            background-color: red;
            position: absolute;
            border-radius: 50% 50% 0 0;
            box-shadow: 0 2px 4px gold;
        }
        
        .item{
            width: 200px;
            height: 60px;
            background: black;
            color: white;
            position: fixed;
            font-size: 30px;
            line-height: 60px;
            text-align: center;
        }
        /* 得分样式 */
        #score{
            left: 50px;
        }
        /* 目标样式 */
        #target{
            left: 50px;
            top: 70px;
        }
        /* 时间样式 */
        #time{
            right: 50px;
        }
        /* 关卡样式 */
        #level{
            right: 50px;
            top: 70px;
        }
    </style>
</head>
<body>
    <div id="score" class="item">
        <label>得分:</label>
        <label>0</label>
    </div>
    <div id="target" class="item">
        <label>目标:</label>
        <label>20</label>
    </div>
    <div id="time" class="item">
        <label>时间:</label>
        <label>60</label>
    </div>
    <div id="level" class="item">
        <label>关卡:</label>
        <label>1</label>
    </div>
    <div id="box">
        <div id="plane"></div>
        <div id="msg">回车键：开始/暂停</div>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
    <script>
        //获取飞机对象
        let plane = $('#plane')
        //初始化飞机的位置
        //innerWidth()方法，返回元素的可见宽度。innerHeight()方法，返回元素的可见高度
        plane.css({
            bottom:'0px',
            left:($('#box').innerWidth()/2 - $('#plane').innerWidth()/2)+'px'
        })

        //生成敌机的方法
        let timer1 = null
        let speed1 = 1000
        function createEnemy(){
            timer1 = setInterval(() => {
                let enemy = $('<div class="enemy" />')
                enemy.css({
                    top:'0px',
                    left:Math.floor(Math.random()*($('#box').innerWidth()-40))+'px'
                })
                $('#box').append(enemy)
            }, speed1);
        }
        

        //敌机下落的方法
        let timer2 = null
        let speed2 = 500  //敌机下落的速度
        function enemyDown(){
            timer2 = setInterval(() => {
                $('.enemy').each(function(index,enemy){
                    let top = $(enemy).position().top  //获取敌机当前的top
                    let left = $(enemy).position().left  //获取敌机当前的left
                    top += 20
                    left = Math.round(Math.random())?left+20:left-20
                    //更新敌机的位置
                    $(enemy).css({
                        top:top+'px',
                        left:left+'px'
                    })
                    //判断敌机的top位置，如果超过了盒子的高度，就删除敌机
                    if(top>$('#box').innerHeight()){
                        $(enemy).remove()
                    }
                })
            },speed2);
        }
        

        //让子弹飞一会儿的方法
        let timer3 = null
        function bulletUp(){
            timer3 = setInterval(() => {
                $('.bullet').each(function(index,bullet){
                    //获取子弹当前的top
                    let top = $(bullet).position().top
                    top -= 20
                    //更新子弹的位置
                    $(bullet).css({
                        top:top+'px'
                    })
                    //判断子弹如果已经飞出去，就删除
                    if(top+$(bullet).innerHeight()<=0){
                        $(bullet).remove()
                    }
                })
            }, 200);
        }

        //碰撞方法
        let timer4 = null
        function checkCollision(){
            timer4 = setInterval(() => {
                // 循环所有敌机
                $('.enemy').each(function(index,enemy){
                    //获取敌机的位置
                    let p1 = returnDOM_trbl(enemy)
                    //循环所有子弹
                    $('.bullet').each(function(index,bullet){
                        //获取子弹的位置
                        let p2 = returnDOM_trbl(bullet)
                        //判断子弹跟敌机是否碰撞
                        if(isCollision(p1,p2)){
                            $(enemy).remove()   //删除敌机
                            $(bullet).remove()  //删除子弹
                            //获取当前得分
                            let count = parseInt($("#score label").eq(1).text())+1
                            //更新最新得分
                            $("#score label").eq(1).text(count)
                        }
                    })
                    //获取飞机的位置
                    let p3 = returnDOM_trbl(plane[0])
                    //判断敌机根据飞机是否碰撞
                    if(isCollision(p1,p3)){
                        plane.remove()      //删除飞机
                        $(enemy).remove()   //删除敌机
                        $('#msg').text('Gave Over ~')  //更新消息框里面的内容
                        $('#msg').show()               //显示消息框
                        clearTimer()  //调用清空定时器的方法
                    }
                })
            }, 50);
        }

        //倒计时定时器
        let timer5 = null
        function countdown(){
            timer5 = setInterval(() => {
                //获取当前剩余时间
                let time = parseInt($("#time label").eq(1).text())-1
                //更新剩余时间
                $("#time label").eq(1).text(time)
                //如果时间为0
                if(time===0){
                    //获取得分
                    let count = parseInt($("#score label").eq(1).text())
                    //获取目标得分
                    let target = parseInt($("#target label").eq(1).text())
                    if(count>=target){
                        //过关
                        $("#score label").eq(1).text(0)         //得分清零
                        $("#target label").eq(1).text(target+=5)   //更新目标得分
                        $("#time label").eq(1).text(60)         //时间恢复60秒
                        //获取当前关卡
                        let level = parseInt($("#level label").eq(1).text())+1
                        //判断是否全部通关
                        if(level===11){
                            clearTimer()  //调用清空定时器的方法
                            $('#msg').html('好厉害！恭喜通关成~')
                            $('#msg').show()   //显示消息框
                            return   //跳出程序
                        }
                        $("#level label").eq(1).text(level)  //更新最新关卡
                        speed1-=50   //更新生成敌机的速度
                        speed2-=50   //更新飞机下落的速度
                        clearInterval(timer1)   //清空生成敌机定时器
                        createEnemy()           //重开生成敌机定时器
                        clearInterval(timer2)   //清空敌机下落定时器
                        enemyDown()             //重开敌机下落定时器
                    }else{
                        //失败
                        plane.remove()      //删除飞机
                        $(enemy).remove()   //删除敌机
                        $('#msg').text('Gave Over ~')  //更新消息框里面的内容
                        $('#msg').show()               //显示消息框
                        clearTimer()  //调用清空定时器的方法
                    }
                }
            }, 1000);
        }
        
        //判断两个DOM元素，是否碰撞
        function isCollision(p1,p2){
            if(p1.l>p2.l && p1.l<p2.r && p1.t>p2.t && p1.t<p2.b||
            p1.r>p2.l && p1.r<p2.r && p1.t>p2.t && p1.t<p2.b||
            p1.l>p2.l && p1.l<p2.r && p1.b>p2.t && p1.b<p2.b||
            p1.r>p2.l && p1.r<p2.r && p1.b>p2.t && p1.b<p2.b||
            p2.l>p1.l && p2.l<p1.r && p2.t>p1.t && p2.t<p1.b||
            p2.r>p1.l && p2.r<p1.r && p2.t>p1.t && p2.t<p1.b||
            p2.l>p1.l && p2.l<p1.r && p2.b>p1.t && p2.b<p1.b||
            p2.r>p1.l && p2.r<p1.r && p2.b>p1.t && p2.b<p1.b){
                return true
            }else{
                return false
            }
        }

        //创建子弹的方法
        let date=null   //定义一个时间对象，对创建子弹操作进行节流
        function createBullet(){
            if(new Date()-date>300){
                let bullet = $('<div class="bullet"/>')
                $('#box').append(bullet)
                //获取飞机的位置信息
                let plane_prosition = returnDOM_trbl(plane[0])
                //设置子弹的位置
                bullet.css({
                    top:plane_prosition.t-bullet.innerHeight()+'px',
                    left:plane_prosition.l+(plane.innerWidth()/2)-(bullet.innerWidth()/2)+'px'
                })
                date = new Date()
            }
        }

        //飞机移动的方法
        function planeMove(type){
            let top = plane.position().top   //获取飞机的上边距
            let left = plane.position().left //获取飞机的左边距
            switch(type){
                case "t":
                    top -= 20
                    if(top<=0) top = 0
                    break
                case "b":
                    top += 20
                    if(top>=$('#box').innerHeight()-plane.innerHeight()) 
                        top = $('#box').innerHeight()-plane.innerHeight()
                    break
                case 'l':
                    left -= 20
                    if(left<=0) left = 0
                    break
                case 'r':
                    left += 20
                    if(left>=$('#box').innerWidth()-plane.innerWidth())
                        left = $('#box').innerWidth()-plane.innerWidth()
                    break
            }
            //更新飞机的位置
            plane.css({
                left:left+'px',
                top:top+'px'
            })
        }

        //键盘按下事件
        $(window).keydown(function(e){
            //获取按键号码
            let {keyCode} = e
            switch(keyCode){
                //生成子弹
                case 32: 
                    if(timer3!==null){
                        createBullet() //调用创建子弹的方法 
                    }
                    break;
                //上
                case 38:
                    planeMove('t')
                    break;
                //下
                case 40:
                    planeMove('b')
                    break; 
                //左
                case 37: 
                    planeMove('l')
                    break;
                //右
                case 39: 
                    planeMove('r')
                    break;
                //如果是回车键，运行/暂停
                case 13: 
                    //如果生成敌机的定时器是null
                    if(timer1===null){
                        //如果消息框里面的内容不是'Gave Over ~'，则开始游戏
                        if($('#msg').text()==='回车键：开始/暂停'){
                            createEnemy()       //开启生成敌机定时器
                            enemyDown()         //开启敌机下落定时器
                            bulletUp()          //开启子弹上飞定时器
                            checkCollision()    //开启碰撞定时器
                            countdown()         //开始倒计时定时器
                            $('#msg').hide()    //隐藏消息框
                        }
                    }else{
                        //暂停
                        clearTimer()  //调用清空定时器的方法
                        $('#msg').show()   //显示消息框
                    }
                    break;
            }
        })

        //清空定时器的方法
        function clearTimer(){
            clearInterval(timer1)   //清除生成敌机的定时器
            timer1 = null
            clearInterval(timer2)   //清除敌机下落的定时器
            timer2 = null
            clearInterval(timer3)   //清除子弹上飞的定时器
            timer3 = null
            clearInterval(timer4)   //清除碰撞定时器
            timer4 = null
            clearInterval(timer5)   //清除倒计时定时器
            timer5 = null
        }

        //该方法，用于返回一个DOM元素的top，right，bottom，left到父级的距离
        function returnDOM_trbl(dom){
            let t = dom.offsetTop
            let r = dom.offsetLeft+dom.offsetWidth
            let b = dom.offsetTop+dom.offsetHeight
            let l = dom.offsetLeft
            return {
                t,r,b,l
            }
        }
    </script>
</body>
</html>